package communication.common.business.hole;

import communication.common.business.base.*;
import communication.common.business.heartbeat.HeartBeatServiceCommon;
import communication.common.business.util.MsgDataUtil;
import communication.common.vertx.net.ConnectRecord;
import communication.common.vertx.net.NetManager;
import io.vertx.core.datagram.DatagramSocket;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


/**
 * 处理打洞数据的handler
 * @author zxl
 */
@Component
@Slf4j
public class DefaultHoleHandler {

    @Autowired
    private NetManager netManager;

    @Autowired
    private FcrAutoConfig fcrAutoConfig;

    /**
     *   处理打洞测试的请求
     *
     *  1.生成随机数 R
     *  2.比较 R 与 weight的大小
     *  3. 如果R > weight， 则大的一方作为client端，小的一方作为server端*
     *  4. 返回给对端工作模式
     *  5. 记录远端的工作模式
     * @return
     */
    public WorkModeEnum handleHoleTestReq(Integer weight, FcrSocketAddress remoteAddress){
        log.info(" 开始处理 -- [handleHoleTestReq]--weight:{}--remoteAddress:{}",weight,remoteAddress);

        WorkModeEnum workModeEnum = null;

        // 如果本段实际工作模式是server端，那么直接指定对端为client
        if(WorkModeEnum.SERVER.equals(fcrAutoConfig.getWorkMode()) ){
            return WorkModeEnum.CLIENT;
        }

        // 生成随机数，直到与传入的weight不一样
        int myWeight = NetManager.random.nextInt();
        while( myWeight == weight ){
            myWeight = NetManager.random.nextInt();
        }



        if(myWeight < weight ){
            // 远端做client端
            workModeEnum = WorkModeEnum.CLIENT;
        }else {
            // 远端做server端
            workModeEnum = WorkModeEnum.SERVER;
        }

        // todo: 目前打洞只支持udp，记录远端的工作模式
        ConnectRecord<DatagramSocket> udpRecord = netManager.getUdpRemoteSocketRecord().get(remoteAddress);
        if(udpRecord != null ){
            udpRecord.setRemoteMode(workModeEnum);
        }

        log.info(" 处理完成 -- [handleHoleTestReq]-- remoteAddress:{} -- remoteMode:{}",remoteAddress,workModeEnum);
        return workModeEnum;
    }


    /**
     * 处理测试打洞请求的响应
     * @param localMode 本段的工作模式
     * @param remoteAddress 远端地址
     * @return
     */
    public void handleHoleTestResp(WorkModeEnum localMode, FcrSocketAddress remoteAddress){
        log.info(" 开始处理 -- [handleHoleTestResp]--localMode:{}--remoteAddress:{}",localMode,remoteAddress);

        // 记录工作模式
        ConnectRecord<DatagramSocket> record = netManager.getUdpRemoteSocketRecord().get(remoteAddress);
        if(record != null){
            WorkModeEnum remoteMode = WorkModeEnum.revertMode(localMode);
            record.setRemoteMode(remoteMode );
            if(remoteMode.equals(WorkModeEnum.SERVER)){
                log.info("处理中 -- [handleHoleTestResp]--对端模式:Server --remoteAddress:{}, 之后将发送心跳给对端！",remoteAddress);
            }
        }

        log.info(" 处理完成 -- [handleHoleTestResp]--remoteAddress:{}",remoteAddress);
    }

}
